package Master

//让Web调用的任务管理组件
import (
	"MserviceTask/Common"
	"context"
	"encoding/json"
	"github.com/coreos/etcd/clientv3"
	"log"
	"time"
)

/**
任务管理器
*/
type JobManage struct {
	client *clientv3.Client
	kv     clientv3.KV
	lease  clientv3.Lease
}

var (
	G_JobManage *JobManage
)

//创建一个任务管理器
func NewJobManage() (err error) {
	var (
		etcdConfig clientv3.Config
		client     *clientv3.Client
		kv         clientv3.KV
		lease      clientv3.Lease
	)
	etcdConfig = clientv3.Config{
		//集群地址
		Endpoints:   []string{Common.G_CONF.String("ETCD.hosts")},
		DialTimeout: time.Duration(5) * time.Second,
	}
	if client, err = clientv3.New(etcdConfig); err != nil {
		return
	}
	kv = clientv3.NewKV(client)
	lease = clientv3.NewLease(client)
	G_JobManage = &JobManage{
		client: client,
		kv:     kv,
		lease:  lease,
	}
	return
}

//保存任务到ETCD
func (t *JobManage) Save(job *Common.JobItem) (oldJob *Common.JobItem, err error) {
	var (
		jobKey     string
		jobJsonVal []byte
		putResp    *clientv3.PutResponse
		oldJobObj  Common.JobItem
	)
	//任务保存的key
	jobKey = Common.JOB_KEY_DIR + job.Name

	if jobJsonVal, err = json.Marshal(job); err != nil {
		return
	}
	//保存到ETCD
	if putResp, err = t.kv.Put(context.TODO(), jobKey, string(jobJsonVal), clientv3.WithPrevKV()); err != nil {
		return
	}
	//如果是更新
	if putResp.PrevKv != nil {
		if err = json.Unmarshal(putResp.PrevKv.Value, &oldJobObj); err != nil {
			err = nil
			return
		}
		oldJob = &oldJobObj
	}
	return
}

//删除任务
func (t *JobManage) Delete(name string) (oldJson *Common.JobItem, err error) {
	var (
		jobKey     string
		deleteResp *clientv3.DeleteResponse
		oldJsonVal Common.JobItem
	)
	jobKey = Common.JOB_KEY_DIR + name
	if deleteResp, err = t.kv.Delete(context.TODO(), jobKey, clientv3.WithPrevKV()); err != nil {
		return
	}
	if len(deleteResp.PrevKvs) == 0 {
		if err = json.Unmarshal(deleteResp.PrevKvs[0].Value, &oldJsonVal); err != nil {
			return
		}
		oldJson = &oldJsonVal
	}
	return
}

//杀死任务
func (t *JobManage) Kill(name string) (err error) {
	var (
		jobKey             string
		leaseGrantResponse *clientv3.LeaseGrantResponse
		leaseId            clientv3.LeaseID
		putResponse        *clientv3.PutResponse
	)
	jobKey = Common.JOB_KEY_DIR + name
	if leaseGrantResponse, err = t.lease.Grant(context.TODO(), 1); err != nil {
		return
	}
	//租约ID
	leaseId = leaseGrantResponse.ID
	//设置Kill标志
	if putResponse, err = t.kv.Put(context.TODO(), jobKey, "", clientv3.WithLease(leaseId)); err != nil {
		return
	}
	log.Print(putResponse)
	return
}
